<?php

/**
* manipulator for physical path node
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 2006-01-26 15:06:29
*/
class PathNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
    /**
    * use pathNode::getNode to get an appropriate instance
    * @access private
    * /
    function pathNode($path) {
        $this->__construct($path);
    }/**/

    /**
    * "real" constructor.
    * use parent::__construct in subclasses to call parent constructor
    * @access public
    */
    protected function __construct($path) {
        $this->setInfo($path);
    }/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
    /**
    * returns appropriate instance of pathNode or pathNode subclass
    * @static
    * @param string $path
    * @access public
    * @return pathNode|folderNode|fileNode etc
    */
    public function & getNode($path) {
        $n=NULL;
        // getting path node heritage class list by specifity desc
        $classes=pathNode::heritage();
        foreach ($classes as $class) {
            //$detection=$class::selfDetector($path)
            $detection=call_user_func(array(&$class, "selfDetector"),$path);
            if ($detection) {
                // echo "<br />detected $class for $path ! ";
                $n=&new $class($path);
                return $n;
            }
        }
        if (is_null($n)) {
            trigger_error("pathnode::getnode(): no pathnode class found for $path");
        }
        return $n;
    }/**/

    /**
    * retrieve all subclasses and edventually declare a new subclass
    * If $class is provided, add a subclass to
    * @param string $class
    * @param int $specificity 01-99, default 20 higher specificity override more generic classes
    * @access public
    * @static
    * @return array classes name with keys sheme specificity-classname, sorted on keys desc
    */
    public static function heritage($class=NULL,$specificity=20) {
        static $classes;
        // basic classes
        $classes['01-pathnode']='pathnode';
        //$classes['02-filenode']='filenode';
        //$classes['02-foldernode']='foldernode';
        // adding subclass
        if (is_string($class) and is_int($specificity) and !in_array($class,$classes)) {
            $specificity=sprintf('%02d',$specificity);
            $class=strtolower($class);
            $classes["$specificity-$class"]=$class;
        }
        // sorting by specificity desc
        krsort($classes);
        return $classes;
    }/**/

    /**
    * sets a reference to parent node
    * @param pathNode &$node
    * @access public
    * @return bool
    */
    public function setParent(&$node) {
        if (!is_a($node,'pathnode')) return false;
        $this->_parent=&$node;
        return true;
    }/**/

    /**
    *
    * @access public
    * @return string basename
    */
    public function getBaseName() {
        return $this->basename;
    }/**/

    /**
    * returns path from the main script directory
    * @param
    * @access public
    * @return string
    */
    public function getRelativePath() {
        return $this->relative_path;
    }/**/

    /**
    * alias for getrelative path
    * @param
    * @access public
    * @return string
    */
    public function getPath() {
        return $this->getRelativePath();
    }/**/

    /**
    * does the file exists ?
    * @access public
    * @return bool
    */
    function exists() {
        return file_exists($this->path);
    }/**/

    /**
    *
    * @param
    * @access public
    * @return
    * /
    function () {

    }/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
    /**
    * @var type desc
    */
    //var $pathInfo; // information array about path
    //var $type='path';
    protected $_parent;
    protected $exists;
    protected $basename;
    protected $path; // full path
    protected $relative_path; // path from current main script
    protected $absolute_path; // path from server root
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
    /**
    * detects if path applies to self class.
    * subclasses HAVE to implement this method
    * @param
    * @access protected
    * @return bool
    */
    protected function selfDetector($path) {
        return false;
    }/**/

    /**
    * sets main path information properties from path
    * @param string $path
    * @access protected
    * @return bool
    */
    protected function setInfo($path) {
        // translating windows path to standard ones
        $path=str_replace('\\','/',$path);
        $this->path=$path;
        $realpath=realpath($path);
        // a dirty hack for some web hosts using absolute paths
        if (PHP_OS!='WINNT' and substr($realpath,0,1)!='/')
            $realpath='/'.$realpath;
        $this->exists=file_exists($realpath);
        $parts=pathinfo($realpath);
        $this->basename=$parts['basename'];
        $this->absolute_path=$realpath;
        // getting relative path by substracting main script's dirname from absolute path
        //$base_path=
        $this->relative_path=substr($realpath
            ,strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1);
        // translating windows paths to standard ones
        //$this->path=str_replace('\\','/',$this->path);
        //$this->relative_path=str_replace('\\','/',$this->relative_path);
        return true;
    }/**/

    /**
    *
    * @param
    * @access private
    * @return
    * /
    function () {

    }/**/
}